package com.yjz.log;

import androidx.annotation.NonNull;

import com.yjz.log.config.JLogConfig;
import com.yjz.log.config.YLogType;
import com.yjz.log.manager.JLogManager;
import com.yjz.log.print.ILogPrinter;
import com.yjz.log.util.StackTraceUtil;

import java.util.Arrays;
import java.util.List;

/**
 * 作用 : 日志类
 * 作者 : yjz
 * 时间 : 2024/9/13 17:20
 */
public class JLog {

    private static final String Y_LOG_PACKAGE;

    static {
        // 获取到当前类的全路径
        String className = JLog.class.getName();
        // 裁剪获取到当前的类的包名
        Y_LOG_PACKAGE = className.substring(0, className.lastIndexOf("."));
    }

    public static void vTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.V, tag, contents);
    }

    public static void v(Object... contents) {
        vTag(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    public static void dTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.D, tag, contents);
    }

    public static void d(Object... contents) {
        dTag(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    public static void iTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.I, tag, contents);
    }

    public static void i(Object... contents) {
        iTag(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    public static void wTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.W, tag, contents);
    }

    public static void w(Object... contents) {
        wTag(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    public static void eTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.E, tag, contents);
    }

    public static void e(Object... contents) {
        eTag(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    public static void aTag(String tag, Object... contents) {
        log(JLogManager.getInstance().getConfig(), YLogType.A, tag, contents);
    }

    public static void a(Object... contents) {
        a(JLogManager.getInstance().getConfig().getGlobalTag(), contents);
    }

    private static void log(@NonNull JLogConfig config, @YLogType.TYPE int type, @NonNull String tag, Object... contents) {
        if (!config.enable()) return;

        JLogConfig.JsonParse jsonParse = config.injectJsonParser();
        if (jsonParse == null) {
            throw new NullPointerException("JsonParse is null!");
        }

        StringBuilder stringBuilder = new StringBuilder();
        // 打印是否包含线程信息
        boolean includeThread = config.includeThread();
        if (includeThread) {
            String format = JLogConfig.THREAD_INFO_FORMATTER.format(Thread.currentThread());
            stringBuilder.append("├ ").append(format).append("\n");
        }

        // 打印堆栈信息
        if (config.stackDepth() > 0) {
            String format = JLogConfig.STACK_INFO_FORMATTER.format(StackTraceUtil.getCroppedRealStackTrack(new Throwable().getStackTrace(), Y_LOG_PACKAGE, config.stackDepth()));
            stringBuilder.append("├ ").append(format).append("\n");
        }

        String content = parseBody(contents, config);
        stringBuilder.append("├ ").append(content);

        // 打印器类
        List<ILogPrinter> printer = config.printer() != null ? Arrays.asList(config.printer()) : JLogManager.getInstance().getPrinters();
        if (printer == null || printer.isEmpty()) return;
        // 获取到所有的打印器进行打印
        for (ILogPrinter logPrinter : printer) {
            logPrinter.print(type, tag, stringBuilder.toString());
        }
    }

    // 格式化需要打印的内容
    private static String parseBody(@NonNull Object[] contents, @NonNull JLogConfig config) {
        if (config.injectJsonParser() != null) {
            //只有一个数据且为String的情况下不再进行序列化
            if (contents.length == 1 && contents[0] instanceof String) {
                return (String) contents[0];
            }
            return config.injectJsonParser().toJson(contents);
        }
        StringBuilder sb = new StringBuilder();
        for (Object o : contents) {
            sb.append(o.toString()).append(";");
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }
}
